package com.mtr.databoard.application.components;

import com.mtr.databoard.application.EntityResultDto;
import com.mtr.databoard.application.PagedResultDto;
import com.mtr.databoard.application.components.dto.ViewComponentDto;
import com.mtr.databoard.application.components.dto.CreateComponentInput;
import com.mtr.databoard.application.components.dto.UpdateComponentInput;
import com.mtr.databoard.common.linqlist.LinqList;
import com.mtr.databoard.domain.components.ComponentManager;
import com.mtr.databoard.domain.components.IComponentRepository;
import com.mtr.databoard.domain.components.ViewComponent;
import com.mtr.databoard.domain.resources.ResourceManager;
import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("component")
public class ViewComponentApplication {

    private ComponentManager componentManager;
    private IComponentRepository componentRepository;
    private ResourceManager resourceManager;

    public ViewComponentApplication(@Autowired ComponentManager componentManager, @Autowired IComponentRepository componentRepository,@Autowired ResourceManager resourceManager) {
        this.componentManager = componentManager;
        this.componentRepository = componentRepository;
        this.resourceManager = resourceManager;
    }

    @GetMapping("/getall")
    @ResponseBody
    public EntityResultDto<PagedResultDto<ViewComponentDto>> getAllViewComponents() {
        List<ViewComponent> components = componentRepository.findAll();
        LinqList<ViewComponent> linqComponents = new LinqList<>(components);
        List<ViewComponentDto> results =linqComponents.select(c->{
            return new ViewComponentDto(c.getId(),c.getCover(),c.getName(),c.getCode(),c.getDescription(),c.getSize(),c.getUpdateTime(),c.getHtmlbody());
        }).toList();
        return EntityResultDto.newSuccessResult(new PagedResultDto<>(components.size(), results));
    }

    @GetMapping("/get/{id}")
    @ResponseBody
    public EntityResultDto<ViewComponent> getViewComponent(@PathVariable UUID id) {
        if (!componentRepository.existsById(id)) return EntityResultDto.newErrorResult(null);
        ViewComponent component = componentRepository.findById(id).get();
        return EntityResultDto.newSuccessResult(component);
    }

    @DeleteMapping("/delete/{id}")
    @ResponseBody
    public EntityResultDto<ViewComponent> deleteViewComponent(@PathVariable UUID id) {
        if (!componentRepository.existsById(id)) return EntityResultDto.newErrorResult(null);

        ViewComponent component = componentRepository.findById(id).get();
        componentManager.delete(id);
        return EntityResultDto.newSuccessResult(component);
    }

    @PostMapping("/copy/{id}")
    @ResponseBody
    public EntityResultDto<ViewComponent> copyViewComponent(@PathVariable UUID id) throws CloneNotSupportedException, IOException {
        if (!componentRepository.existsById(id)) return EntityResultDto.newErrorResult(null);

        ViewComponent component = componentManager.copy(id);
        return EntityResultDto.newSuccessResult(component);
    }



    @PostMapping("/create")
    @ResponseBody
    public EntityResultDto<ViewComponent> createViewComponent(@RequestBody CreateComponentInput input) {
        ViewComponent component = new ViewComponent(input.getName());
        componentRepository.insert(component);
        return EntityResultDto.newSuccessResult(component);
    }

    @PutMapping("/update")
    @ResponseBody
    public EntityResultDto<ViewComponent> updateViewComponent(@RequestBody UpdateComponentInput input) throws IOException {
        if (!componentRepository.existsById(input.getId()))
            return EntityResultDto.newErrorResult(null);
        componentManager.update(input.getId(),input.getCover(), input.getName(), input.getCode(), input.getDescription(), input.getSize(), input.getResources(), input.getHeadLinks(), input.getCodes(),input.getHtmlbody(),input.getCustomerOptions());


        return EntityResultDto.newSuccessResult(componentRepository.findById(input.getId()).get());
    }

    @GetMapping("/resource/{componentId}/**")
    @ResponseBody
    public void getComponentResource(@PathVariable UUID componentId, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        String resourcePath = request.getRequestURI().split(componentId.toString())[1];
        resourcePath = URLDecoder.decode(resourcePath, "utf-8");
        Binary content = resourceManager.getFileContent("compreview", componentId.toString(), resourcePath);
        if (content == null) return;

        String fileName = new File(resourcePath).getName();

        response.setContentType("octet-stream");
        response.setHeader("Content-Disposition", ";filename=" + fileName);

        OutputStream os = null;
        try {
            os = response.getOutputStream();
            os.write(content.getData());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                os.close();
            } catch (Exception ex) {

            }
        }
    }

    @GetMapping("/preview/{id}")
    public String preview(@PathVariable UUID id, Model m) {
        if (!componentRepository.existsById(id)) return "viewComponent/empty";
        ViewComponent component = componentRepository.findById(id).get();
        if (component.getHeadLinks() != null) {
            component.setHeadLinks(fillEnvironmentVariables(component.getHeadLinks(),component));
        }
        if(component.getCodes()!=null)
            component.setCodes(fillEnvironmentVariables(component.getCodes(),component));
        if(component.getHtmlbody()!=null)
            component.setHtmlbody(fillEnvironmentVariables(component.getHtmlbody(),component));
        m.addAttribute("component", component);
        return "viewComponent/preview";
    }

    /**
     * 填充环境变量，替换实际值
     * @param content
     * @param component
     * @return
     */
    private String fillEnvironmentVariables(String content,ViewComponent component)
    {
        //资源路径
        content = content.replaceAll("\\{filedir\\}", "/component/resource/"+component.getId().toString());
        //组件id
        content = content.replaceAll("\\{componentId\\}", component.getId().toString());
        return content;
    };

}
